package com.droid.network.base;

import android.app.Application;
import android.content.Context;

import com.droid.network.converter.GsonConverterFactory;
import com.droid.network.cookie.CookieJarImpl;
import com.droid.network.cookie.store.MemoryCookieStore;
import com.droid.network.exception.HttpExceptionHandle;
import com.droid.network.interceptor.CacheInterceptor;
import com.droid.network.interceptor.CommonRequestInterceptor;
import com.droid.network.interceptor.CommonResponseInterceptor;
import com.droid.network.interceptor.HttpLoggingInterceptor;
import com.droid.network.utils.HttpsUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

import androidx.annotation.NonNull;
import io.reactivex.Observable;
import io.reactivex.ObservableTransformer;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ConnectionPool;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

/**
 *  网络接口基类
 * @author zhyuc
 * @since 2019/9/24 18:30
 */
public abstract class NetworkApi {

    protected INetworkRequiredInfo mRequiredInfo;
    private String mBaseUrl;
    private Map<String, Retrofit> mRetrofitMap = new HashMap<>();
    protected Context mContext;

    /**
     * 超时时间
     */
    public static final int TIMEOUT = 5000;

    protected NetworkApi(String baseUrl) {
        this.mBaseUrl = baseUrl;
    }

    public void init(INetworkRequiredInfo requiredInfo, Application appContext) {
        mRequiredInfo = requiredInfo;
        mContext = appContext;
    }


    protected Retrofit getRetrofit(Class service) {
        String key = mBaseUrl + service.getName();
        if (mRetrofitMap.get(key) != null) {
            return mRetrofitMap.get(key);
        }
        Retrofit retrofit = new Retrofit.Builder()
                // 设置请求的域名
                .baseUrl(mBaseUrl)
                // 设置解析转换工厂，用自己定义的
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(getOkHttpClient())
                .build();
        mRetrofitMap.put(key, retrofit);
        return retrofit;
    }


    private OkHttpClient getOkHttpClient() {
        OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();

        if(mContext != null) {
            okHttpClient.addInterceptor(new CommonRequestInterceptor(mContext, mRequiredInfo))
                    .addInterceptor(new CommonResponseInterceptor(mContext, mRequiredInfo));

            // 设置缓存拦截器
            CacheInterceptor cacheInterceptor = new CacheInterceptor(mContext);
            cacheInterceptor.setExpireTime(1000 * 60 * 60);
            okHttpClient.addInterceptor(cacheInterceptor);
        }

        // 增加Cookie
        if (isCookieJar()) {
            okHttpClient.cookieJar(new CookieJarImpl(new MemoryCookieStore()));
        }

        okHttpClient.addInterceptor(getInterceptor());

        // elder：养老平台
        if (!mRequiredInfo.getPlatform().equals("elder")) {
            okHttpClient.addInterceptor(getReceiveCookieInterceptor());
        }

        // 设置超时
        okHttpClient.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(TIMEOUT, TimeUnit.SECONDS);

        // 安全连接
        if(mRequiredInfo != null && mRequiredInfo.isSslSocket()){
            HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory();
            okHttpClient.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager);
        }

        if (mRequiredInfo != null && mRequiredInfo.isDebug()) {
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(mRequiredInfo.getTag());
            loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);
            loggingInterceptor.setColorLevel(Level.WARNING);
            okHttpClient.addInterceptor(loggingInterceptor);
        }

        okHttpClient.connectionPool(new ConnectionPool(8, 15, TimeUnit.SECONDS));
        return okHttpClient.build();
    }

    public <T> ObservableTransformer<T, T> applySchedulers(@NonNull final Observer<T> observer) {
        return upstream -> {
            Observable<T> observable = upstream.subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .map(getAppErrorHandle())
                    .onErrorResumeNext(new HttpResponseFunc());
            observable.subscribe(observer);
            return observable;
        };
    }

    public <T> ObservableTransformer<T, T> applySchedulers() {
        return upstream -> {
            Observable<T> observable = upstream.subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
//                    .map(getAppErrorHandle())
                    .onErrorResumeNext(new HttpResponseFunc());
            return observable;
        };
    }

    /**
     * 创建API服务
     */
    public <T> T getService(@NonNull Class<T> service) {
        return getRetrofit(service).create(service);
    }

    private static class HttpResponseFunc<T> implements Function<Throwable, Observable<T>> {
        @Override
        public Observable<T> apply(Throwable t) {
            return Observable.error(HttpExceptionHandle.handleException(t));
        }
    }

    protected abstract Interceptor getInterceptor();

    protected Interceptor getReceiveCookieInterceptor(){
        return chain -> null;
    }

    protected abstract <T> Function<T, T> getAppErrorHandle();

    protected abstract boolean isCookieJar();
}
